﻿using Microsoft.AspNetCore.Mvc;
using Minio.DataModel.Args;
using RuYiAdmin.Net.DataModel.EntityDataModel.Sys;
using RuYiAdmin.Net.SystemService.BusinessService.Interface.Sys;
using RuYiAdmin.Net.UniversalFoundation.Configurations;
using RuYiAdmin.Net.UniversalFoundation.Contexts;
using RuYiAdmin.Net.UniversalFoundation.Enums.Business;
using RuYiAdmin.Net.UniversalFoundation.Enums.Framework;
using RuYiAdmin.Net.UniversalFoundation.GeneralFoundationClass;
using RuYiAdmin.Net.UniversalFoundation.Models;
using RuYiAdmin.Net.UniversalFoundation.Utils;
using RuYiAdmin.Net.WebApi.RuYiAdminCode.RuYiAdminAnnotation;
using RuYiAdmin.Net.WebApi.RuYiAdminCode.RuYiAdminBase;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace RuYiAdmin.Net.WebApi.RuYiAdminController.Sys
{
    /// <summary>
    /// 业务附件管理控制器
    /// </summary>
    public class SysAttachmentManagementController : RuYiAdminBaseController<SysAttachment>
    {
        #region 属性及构造函数

        /// <summary>
        /// 业务附件业务接口实例
        /// </summary>
        private readonly ISysAttachmentService AttachmentService;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="AttachmentService"></param>
        public SysAttachmentManagementController(ISysAttachmentService AttachmentService) : base(AttachmentService)
        {
            this.AttachmentService = AttachmentService;
        }

        #endregion

        #region 上传业务附件

        /// <summary>
        /// 上传业务附件
        /// </summary>
        /// <param name="businessId">业务编号</param>
        /// <returns>ActionResponseResult</returns>
        [HttpPost]
        [RuYiAdminOperationLog(OperationType.UploadFile)]
        public async Task<IActionResult> UploadAttachments(Guid businessId)
        {
            var attachments = new List<SysAttachment>();

            foreach (var item in HttpContext.Request.Form.Files)
            {
                var attachment = new SysAttachment();

                attachment.Create(HttpContext);
                attachment.FileName = item.FileName;
                //处理文件大小
                string remark = string.Empty;
                attachment.FileSize = RuYiFileContext.GetFileSize(item, out remark);
                attachment.Remark = remark;
                //保存文件
                attachment.FilePath = await RuYiFileContext.SaveBusinessAttachment(item, attachment.Id.ToString());
                //附件关联业务
                attachment.BusinessId = businessId;

                attachments.Add(attachment);
            }

            var actionResponseResult = await AttachmentService.AddListAsync(attachments, false);
            return Ok(actionResponseResult);
        }

        #endregion

        #region 获取业务附件

        /// <summary>
        /// 获取业务附件
        /// </summary>
        /// <param name="businessId">业务编号</param>
        /// <returns>ActionResponseResult</returns>
        [HttpGet("{businessId}")]
        [RuYiAdminOperationLog(OperationType.QueryList)]
        public async Task<IActionResult> GetAttachments(Guid businessId)
        {
            var searchCondition = new SearchCondition();
            searchCondition.SearchItems = new List<SearchItem>();
            searchCondition.SearchItems.Add(new SearchItem()
            {
                Field = "BusinessId",
                DataType = DataType.Guid,
                SearchMethod = SearchMethod.Equal,
                Value = businessId.ToString()
            });
            //获取附件信息
            var actionResponseResult = await AttachmentService.GetListAsync(searchCondition);
            return Ok(actionResponseResult);
        }

        #endregion

        #region 下载业务附件

        /// <summary>
        /// 下载业务附件
        /// </summary>
        /// <param name="attachmentId">附件编号</param>
        /// <returns>ActionResponseResult</returns>
        [HttpGet("{attachmentId}")]
        [RuYiAdminOperationLog(OperationType.DownloadFile)]
        public async Task<IActionResult> DownloadAttachment(Guid attachmentId)
        {
            var task = await AttachmentService.GetByIdAsync(attachmentId);//获取附件信息
            var attachment = (SysAttachment)task.Object;
            var filePath = attachment.FilePath; //存储路径

            if (RuYiGlobalConfig.MinioConfig.IsEnabled)
            {
                var extension = Path.GetExtension(attachment.FileName);//获取文件拓展名            
                var fileName = String.Join("", attachmentId, extension);//文件名

                String path = Path.Join(RuYiGlobalConfig.DirectoryConfig.GetTempPath(), "/");
                filePath = Path.Join(path, fileName);

                var getObjectArgs = new GetObjectArgs()
                    .WithBucket(RuYiGlobalConfig.MinioConfig.BucketName)
                    .WithObject(RuYiGlobalConfig.DirectoryConfig.GetMinioBusinessAttachmentPath() + "/" + fileName)
                    .WithFile(filePath);
                await RuYiMinioContext.Instance.GetObjectAsync(getObjectArgs);
            }

            var stream = new FileStream(filePath, FileMode.Open);//文件读写流                
            stream.Position = 0;//设置流的起始位置

            return File(stream, "application/octet-stream", attachment.FileName);
        }

        #endregion

        #region 删除业务附件

        /// <summary>
        /// 删除业务附件
        /// </summary>
        /// <param name="attachmentIds">数组串</param>
        /// <returns>ActionResponseResult</returns>
        [HttpDelete("{attachmentIds}")]
        [RuYiAdminOperationLog(OperationType.DeleteEntity)]
        public async Task<IActionResult> DeleteAttachment(string attachmentIds)
        {
            var array = attachmentIds.GetGuidArray();
            var actionResponseResult = await AttachmentService.DeleteRangeAsync(array);

            #region 删除业务文件

            foreach (var item in array)
            {
                var attachment = AttachmentService.GetById(item).Object as SysAttachment;//获取附件信息
                if (RuYiGlobalConfig.MinioConfig.IsEnabled)
                {
                    var removeObjectArgs = new RemoveObjectArgs()
                        .WithBucket(RuYiGlobalConfig.MinioConfig.BucketName)
                        .WithObject(attachment.FilePath);
                    await RuYiMinioContext.Instance.RemoveObjectAsync(removeObjectArgs);
                }
                else
                {
                    RuYiFileContext.DeleteFile(attachment.FilePath);
                }
            }

            #endregion

            return Ok(actionResponseResult);
        }

        #endregion

        #region 系统文件统计

        /// <summary>
        /// 系统文件统计
        /// </summary>
        /// <returns>ActionResponseResult</returns>
        [HttpGet]
        [RuYiAdminOperationLog(OperationType.QueryEntity)]
        [RuYiAdminPermission("attachment:query:list")]
        public async Task<IActionResult> GetSysFileStatisticalInfo()
        {
            //获取统计信息
            var actionResponseResult = await AttachmentService.QuerySysFileStatisticalInfo();
            return Ok(actionResponseResult);
        }

        #endregion

        #region 获取业务附件预览地址

        /// <summary>
        /// 获取业务附件预览地址
        /// </summary>
        /// <param name="attachmentId">业务编号</param>
        /// <returns>ActionResponseResult</returns>
        [HttpGet("{attachmentId}")]
        [RuYiAdminOperationLog(OperationType.QueryEntity)]
        public async Task<IActionResult> GetAttachmentPreviewUrl(Guid attachmentId)
        {
            AttachmentPreviewUrl attachmentPreviewUrl = new AttachmentPreviewUrl();
            SysAttachment attachment = (await this.AttachmentService.GetByIdAsync(attachmentId)).Object as SysAttachment;
            if (RuYiGlobalConfig.MinioConfig.IsEnabled)
            {
                String filePath = attachment.FilePath;
                var presignedGetObjectArgs = new PresignedGetObjectArgs()
                    .WithBucket(RuYiGlobalConfig.MinioConfig.BucketName)
                    .WithObject(filePath)
                    .WithExpiry(RuYiGlobalConfig.MinioConfig.PresignedUrlExpiryTime);
                String filePreviewUrl = await RuYiMinioContext.Instance.PresignedGetObjectAsync(presignedGetObjectArgs);
                attachmentPreviewUrl.PreviewUrl = filePreviewUrl;
            }
            else
            {
                attachmentPreviewUrl.PreviewUrl = attachment.FilePath;
            }
            attachmentPreviewUrl.KkFileViewUrl = RuYiGlobalConfig.MinioConfig.KkFileViewUrl;
            return Ok(ActionResponseResult.Success(attachmentPreviewUrl));
        }

        #endregion
    }
}
